// Copyright 2011-2012, Vanya Davidenko.
// Используемая кодировка: UTF-8.

#ifndef LIBV_FILE_WINDOWS_SFILE_IMPL_HPP_
#define LIBV_FILE_WINDOWS_SFILE_IMPL_HPP_

#ifndef _WIN32
# error "This header should be used in Windows only."
#endif

#include <string>
#include <libv/sfile.h>
#include <libv/stdint.h>
#include <libv/windows_lean.h>
#include <libv/file/basic_file.h>



namespace libv
{

// Методы Write и Read сильно копируют друг друга, однако, объединить их код
// для избежания дублирования не удалось.
bool SFile::WriteImpl(const fpos64& offset,
                      const void* data,
                      const uint32_t data_size)
{
    DWORD num_bytes_written = 0;
    OVERLAPPED o = MakeOverlapped(offset);

    const bool result = ( ::WriteFile(
        file_handle_,
        data,
        data_size,
        &num_bytes_written,
        &o) != FALSE && num_bytes_written == data_size );
    last_error_ = ::GetLastError();

    return result;
}



bool SFile::ReadImpl(const fpos64& offset,
                     void* buffer,
                     const uint32_t buffer_size) const
{
    // Нужно обязательно проверять условие num_bytes_read == buffer_size,
    // так как при достижении чтением EOF ReadFile возвращает TRUE,
    // но устанавливает num_bytes_of_read в 0.
    DWORD num_bytes_read = 0;
    OVERLAPPED o = MakeOverlapped(offset);

    const bool result = ( ::ReadFile(
        file_handle_,
        buffer,
        buffer_size,
        &num_bytes_read,
        &o) != FALSE && num_bytes_read == buffer_size );
    last_error_ = ::GetLastError();

    return result;
}



//////////////////////////////////// PRIVATE ///////////////////////////////////



OVERLAPPED SFile::MakeOverlapped(const fpos64 offset) const
{
    OVERLAPPED overlapped = { 0 };
    ULARGE_INTEGER li_offset;
    li_offset.QuadPart = static_cast<ULONGLONG>(offset);
    overlapped.Offset = li_offset.LowPart;
    overlapped.OffsetHigh = li_offset.HighPart;

    return overlapped;
}

}  // libv

#endif  // LIBV_FILE_WINDOWS_SFILE_IMPL_HPP_
